<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<pre>
    每个实例对象（ object ）都有一个私有属性（称之为 __proto__ ）指向它的构造函数的原型对象（prototype ）。
    该原型对象也有一个自己的原型对象( __proto__ ) ，层层向上直到一个对象的原型对象为 null。
    根据定义，null 没有原型，并作为这个原型链中的最后一个环节。

    <h3>和传统OOP语言的区别</h3>

        在传统的 OOP【面向对象的语言】，首先定义“类”，此后创建对象实例时，类中定义的所有属性和方法都被复制到实例中。

        JavaScript 是在对象实例和它的构造器之间建立一个链接（它是__proto__属性，是从构造函数的prototype属性派生的），
        之后通过上溯原型链，在构造器中找到这些属性和方法。

        function Foobar(){}
        注意: 理解对象的原型（可以通过Object.getPrototypeOf(obj)或者已被弃用的__proto__属性获得）
             与构造函数的prototype属性之间的区别是很重要的。
             前者是每个实例上都有的属性，后者是构造函数的属性。
             也就是说，Object.getPrototypeOf(new Foobar()) 和 Foobar.prototype 指向着同一个对象。
             <pre style="color:red;">
             ########################################################################
                每个实例对象上有  __proto__  属性指向原型   eg:new Foobar()就是实例对象
                每个构造函数上有  prototype  属性指向原型   eg:Foobar 就是构造函数【构造实例对象的函数】【只有函数才会有这个属性】
             ########################################################################
            </pre>

     <h3>原型链</h3>
        JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象，
        对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型，并从中继承方法和属性，一层一层、以此类推。
        这种关系常被称为原型链 (prototype chain)，它解释了为何一个对象会拥有定义在其他对象中的属性和方法。

     <h3>使用Javascript中的原型</h3>
        var doSomething = function(){};
        console.log( doSomething.prototype );
        **********************输出如下代码*****************************
        {
            constructor: ƒ doSomething(),
            __proto__: {
                constructor: ƒ Object(),
                hasOwnProperty: ƒ hasOwnProperty(),
                isPrototypeOf: ƒ isPrototypeOf(),
                propertyIsEnumerable: ƒ propertyIsEnumerable(),
                toLocaleString: ƒ toLocaleString(),
                toString: ƒ toString(),
                valueOf: ƒ valueOf()
            }
        }

    <h3>添加原型属性</h3>
    function doSomething(){}
    doSomething.prototype.foo = "bar";
    console.log( doSomething.prototype );
    **********************输出如下代码*****************************
    {
        foo: "bar",
        constructor: ƒ doSomething(),
        __proto__: {
            constructor: ƒ Object(),
            hasOwnProperty: ƒ hasOwnProperty(),
            isPrototypeOf: ƒ isPrototypeOf(),
            propertyIsEnumerable: ƒ propertyIsEnumerable(),
            toLocaleString: ƒ toLocaleString(),
            toString: ƒ toString(),
            valueOf: ƒ valueOf()
        }
    }

<h3>添加实例</h3>
    var doSomeInstancing = new doSomething();
    doSomeInstancing.prop = "some value"; // add a property onto the object
    console.log( doSomeInstancing );

    {
        prop: <span style="color:red;">"some value"</span>,
        __proto__: {
            foo:<span style="color:red;">"bar"</span>,
            constructor: ƒ doSomething(),
            __proto__: {
                constructor: ƒ Object(),
                hasOwnProperty: ƒ hasOwnProperty(),
                isPrototypeOf: ƒ isPrototypeOf(),
                propertyIsEnumerable: ƒ propertyIsEnumerable(),
                toLocaleString: ƒ toLocaleString(),
                toString: ƒ toString(),
                valueOf: ƒ valueOf()
            }
        }
    }
</pre>
</body>
<script>
    function Person (a=1,b){
        this.a = a
        this.b = b
    }
    Person.prototype.getArgs = function (){
        console.log('a  ',this.a)
        console.log('b  ',this.b)
    }

    let p1 = new Person(1,2)
    console.log(p1.a, '  ' ,p1.b)
    p1.getArgs()

</script>
</html>